﻿using System;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Data.Linq;
using System.Linq;

namespace Eff.Data.Linq
{

    public class BaseDal<T> : DataContext where T : class
    {
        public Table<T> Table { get; private set; }
        public BaseDal()
            : base(ConfigurationManager.ConnectionStrings["default"].ConnectionString)
        {
            Table = GetTable<T>();
        }

        public BaseDal(string connectionName)
            : base(ConfigurationManager.ConnectionStrings[connectionName].ConnectionString)
        {
            Table = GetTable<T>();
        }

        public BaseDal(DbConnection connection, DbTransaction trans)
            : base(connection)
        {
            Transaction = trans;
            Table = GetTable<T>();
        }

        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="query">
        /// System.Linq.IQueryable&lt;T&gt;对象
        /// <para>Linq中使用的查询对象，数据查询源</para>
        /// </param>
        /// <param name="pageInfo">分页信息结构体</param>
        /// <returns>
        /// System.Linq.IQueryable&lt;T&gt;对象
        /// <para>Linq中使用的查询对象，该对象已经进行了分页查询操作</para>
        /// </returns>
        protected IQueryable<T> Page(IQueryable<T> query, PageInfo pageInfo)
        {
            return Page<T>(query, pageInfo);
        }

        /// <summary>
        /// 分页
        /// </summary>
        /// <typeparam name="TK">Linq中使用的Table类</typeparam>
        /// <param name="query">
        /// System.Linq.IQueryable&lt;T&gt;对象
        /// <para>Linq中使用的查询对象，数据查询源</para>
        /// </param>
        /// <param name="pageInfo">分页信息结构体</param>
        /// <returns>
        /// System.Linq.IQueryable&lt;T&gt;对象
        /// <para>Linq中使用的查询对象，该对象已经进行了分页查询操作</para>
        /// </returns>
        protected IQueryable<TK> Page<TK>(IQueryable<TK> query, PageInfo pageInfo)
        {
            pageInfo.RecordCount = query.Count();

            var pageSize = pageInfo.PageSize;
            var skipCount = (pageInfo.CurrentPage - 1) * pageSize;

            query = query.Skip<TK>(skipCount).Take<TK>(pageSize);
            return query;
        }
    }

    /// <summary>
    /// Linq 帮助类
    /// </summary>
    /// <typeparam name="T">Table 的类型</typeparam>
    public class LinqHelper<T> : IDisposable where T : class
    {
        /// <summary>
        /// 获取 默认Table
        /// </summary>
        public Table<T> Table { get; private set; }

        /// <summary>
        /// 获取 DataContext
        /// </summary>
        public DataContext DataContext { get; private set; }

        public LinqHelper()
        {
            DataContext = LinqHelper.GetDataContext();
            Table = DataContext.GetTable<T>();
        }

        public LinqHelper(string connectionName)
        {
            DataContext = LinqHelper.GetDataContext(ConnStrHelper.GetConnStr(connectionName));
            Table = DataContext.GetTable<T>();
        }

        public LinqHelper(IDbConnection connection, DbTransaction trans)
        {
            DataContext = LinqHelper.GetDataContext(connection, trans);
            Table = DataContext.GetTable<T>();
        }

        public LinqHelper(DataContext context)
        {
            DataContext = context;
            Table = DataContext.GetTable<T>();
        }

        public void Dispose()
        {
            DataContext.Dispose();
        }
    }

    /// <summary>
    /// Linq 帮助类
    /// </summary>
    internal class LinqHelper
    {
        /// <summary>
        /// 获取 Linq 使用的 DataContext 对象
        /// <para>使用默认的数据链接，链接名为 DefaultConnectionName 常量中规定的</para>
        /// </summary>
        /// <returns></returns>
        public static DataContext GetDataContext()
        {
            return GetDataContext(ConnStrHelper.GetConnStr(ConnStrHelper.DefaultConnectionName));
        }

        /// <summary>
        /// 获取 Linq 使用的 DataContext 对象
        /// <example>var dataContext = GetDataContext(GetConnStr(connectionName))</example>
        /// </summary>
        /// <param name="connectionString">数据库链接字符串</param>
        /// <returns>DataContext 对象</returns>
        public static DataContext GetDataContext(string connectionString)
        {
            var dataContext = new DataContext(connectionString);

            return dataContext;
        }

        /// <summary>
        /// 获取 Linq 使用的 DataContext 对象
        /// </summary>
        /// <param name="connection">数据链接</param>
        /// <param name="trans">事务</param>
        /// <returns>DataContext 对象</returns>
        public static DataContext GetDataContext(IDbConnection connection, DbTransaction trans)
        {
            var dataContext = new DataContext(connection) { Transaction = trans };

            return dataContext;
        }
    }


}
